﻿using Quartz;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Web;
using TaskManagementSystem.Middleware;

namespace TaskManagementSystem.ScheduledTask
{
    [PersistJobDataAfterExecution]
    [DisallowConcurrentExecution]
    public class ScheduledTaskExecuteBase : IJob
    {
        public void Execute(IJobExecutionContext context)
        {
            Data.DbContext dbContext = new Data.DbContext();
            JobKey jobKey = context.JobDetail.Key;
            DateTime runTime = DateTime.Now;
            DateTime endTime = DateTime.Now;
            DateTime nextTime = DateTime.Now;
            string group = string.Empty;
            string jobKeyStr = string.Empty;
            string resultMsg = string.Empty;

            if (!ScheduledTaskCore.TryGetKeyAndGroup(jobKey, out jobKeyStr, out group))
            {
                Logs.Loggers.Cronlogger.Error(string.Format("无法取得任务JobKey--{0}", jobKey.ToString()));
                return;
            }

            Entity.SystemCronConfigData data = dbContext.SystemCronConfigData.Where(x => x.JobKey == jobKeyStr && x.GroupId == group).FirstOrDefault();
            if (data == null)
            {
                Logs.Loggers.Cronlogger.Error(string.Format("group={0},key={1}任务不存在。", group, jobKeyStr));
                return;
            }

            data.IsRunning = true;
            data.RunTime = runTime;
            dbContext.Entry(data).State = System.Data.Entity.EntityState.Modified;
            dbContext.SaveChanges();

            Stopwatch sw = Stopwatch.StartNew();
            Logs.Loggers.Cronlogger.Info(string.Format("{0}({1})任务开始执行。", data.JobName, jobKey.ToString()));

            try
            {
                Type t = System.Type.GetType(data.Assembly);
                if (Array.IndexOf(t.GetInterfaces(), typeof(IScheduledTask)) == -1)
                {
                    Logs.Loggers.Cronlogger.Error(string.Format("定时任务{0}没有正确继承接口TaskManagementSystem.Middleware.IScheduledTask。", data.JobName));
                    return;
                }
                IScheduledTask task = (IScheduledTask)Activator.CreateInstance(t);
                task.Execute();
                endTime = DateTime.Now;
                resultMsg = "操作成功。";
            }
            catch (Exception ex)
            {
                resultMsg = ex.Message;
                Logs.Loggers.Cronlogger.Fatal(ex);
            }
            sw.Stop();
            TimeSpan ts = TimeSpan.FromMilliseconds(sw.ElapsedMilliseconds);
            bool isTimeOut = false;

            switch ((Entity.Enum.JobType)data.JobType)
            {
                case Entity.Enum.JobType.Seconds:
                    isTimeOut = TimeSpan.Compare(ts, runTime.AddSeconds(data.TimeSpan) - runTime) > 0;
                    nextTime = endTime.AddSeconds(data.TimeSpan);
                    break;
                case Entity.Enum.JobType.Minutes:
                    isTimeOut = TimeSpan.Compare(ts, runTime.AddMinutes(data.TimeSpan) - runTime) > 0;
                    nextTime = endTime.AddMinutes(data.TimeSpan);
                    break;
                case Entity.Enum.JobType.Hours:
                    isTimeOut = TimeSpan.Compare(ts, runTime.AddHours(data.TimeSpan) - runTime) > 0;
                    nextTime = context.NextFireTimeUtc.Value.LocalDateTime;
                    break;
                case Entity.Enum.JobType.Days:
                    isTimeOut = TimeSpan.Compare(ts, runTime.AddDays(data.TimeSpan) - runTime) > 0;
                    nextTime = context.NextFireTimeUtc.Value.LocalDateTime;
                    break;
                case Entity.Enum.JobType.Weeks:
                    isTimeOut = TimeSpan.Compare(ts, runTime.AddDays(data.TimeSpan * 7) - runTime) > 0;
                    nextTime = context.NextFireTimeUtc.Value.LocalDateTime;
                    break;
                case Entity.Enum.JobType.Months:
                    isTimeOut = TimeSpan.Compare(ts, runTime.AddMonths(data.TimeSpan) - runTime) > 0;
                    nextTime = context.NextFireTimeUtc.Value.LocalDateTime;
                    break;
                case Entity.Enum.JobType.Years:
                    isTimeOut = TimeSpan.Compare(ts, runTime.AddYears(data.TimeSpan) - runTime) > 0;
                    nextTime = context.NextFireTimeUtc.Value.LocalDateTime;
                    break;
                case Entity.Enum.JobType.Advanced:
                    isTimeOut = false;
                    nextTime = context.NextFireTimeUtc.Value.LocalDateTime;
                    break;
            }

            data = dbContext.SystemCronConfigData.Where(x => x.JobId == data.JobId).FirstOrDefault();
            data.TimeConsuming = ts.Milliseconds;
            data.ResultMsg = resultMsg;
            data.NextTime = nextTime;
            data.RunTime = runTime;
            data.EndTime = endTime;
            data.IsRunning = false;
            dbContext.Entry(data).State = System.Data.Entity.EntityState.Modified;
            dbContext.SaveChanges();
            Logs.Loggers.Cronlogger.Info(string.Format("{0}({1})任务结束。", data.JobName, jobKey.ToString()));
        }
    }
}